#include "StdAfx.h"

namespace DuiLib
{
/////////////////////////////////////////////////////////////////////////////////////
//
	bool Asc(const CTabPage* t1,const CTabPage* t2)
	{  
		return t1->orderNum < t2->orderNum;  
	}  

	CTabControlUI::CTabControlUI()
	{
		AddTabPageButton=new CTabControlButton;
		AddTabPageButton->id=ADDTABBTN;
		Buttons.push_back(AddTabPageButton);
		CTabPage* tabPage=new CTabPage;
		tabPage->caption=m_DefaultTabPageText;
		tabPage->orderNum=0;
		AddTabPage(tabPage);
	}

	void CTabControlUI::AddTabPage(CTabPage* tabPage)
	{
		std::vector<CTabPage*>::iterator sIter=TabPages.begin();
		int orderNum=0;
		for(unsigned int i=0;i<TabPages.size();i++,sIter++)
		{
			CTabPage* tabPage=*sIter;
			tabPage->state=0;
			if(tabPage->orderNum>orderNum)
			{
				orderNum=tabPage->orderNum;
			}
		}
		tabPage->orderNum=orderNum+1;
		tabPage->state=2;
		CTabControlButton* closeBtn = new CTabControlButton;
		tabPage->closebtn = closeBtn;
		tabPage->movingX = 0;
		Buttons.push_back(closeBtn);
		TabPages.push_back(tabPage);
	}

	void CTabControlUI::ClearButtonState(EVENTTYPE_UI eventType)
	{
		std::vector<CTabControlButton*>::iterator bIter=Buttons.begin();
		for(unsigned int i=0;i<Buttons.size();i++,bIter++)
		{
			CTabControlButton* button=*bIter;
			if(eventType==UIEVENT_BUTTONDOWN)
			{
				button->state = 0;
			}
			else if(eventType==UIEVENT_MOUSEMOVE)
			{
				if(button->state==1)
				{
					button->state=0;
				}
			}
			else if(eventType==UIEVENT_BUTTONUP)
			{
				button->state=0;
			}
		}
	}

	void CTabControlUI::ClearTabPageState(EVENTTYPE_UI eventType)
	{
		std::vector<CTabPage*>::iterator sIter=TabPages.begin();
		for(unsigned int i=0;i<TabPages.size();i++,sIter++)
		{
			CTabPage* tabPage=*sIter;
			if(eventType==UIEVENT_BUTTONDOWN)
			{
				tabPage->state=0;
			}
			else if(eventType==UIEVENT_MOUSEMOVE)
			{
				if(tabPage->state==1)
				{
					tabPage->state=0;
				}
			}
		}
	}

	bool CTabControlUI::Contains(RECT rect,POINT pt)
	{
		if(pt.x>=rect.left && pt.x<=rect.right
			&& pt.y>=rect.top && pt.y<=rect.bottom)
		{
			return true;
		}
		return false;
	}

	RECT CTabControlUI::CopyRect(RECT copyRect)
	{
		RECT rect;
		rect.left=copyRect.left;
		rect.right=copyRect.right;
		rect.top=copyRect.top;
		rect.bottom=copyRect.bottom;
		return rect;
	}

	RECT CTabControlUI::DisplayRect()
	{
		RECT rect;
		rect.left=this->GetX();
		rect.top=this->GetY();
		rect.right=this->GetWidth() + rect.left - 1;
		rect.bottom=this->GetHeight() + rect.top - 1;
		return rect;
	}

	void CTabControlUI::DoEvent(TEventUI& event)
	{
		if( event.Type == UIEVENT_BUTTONDOWN || event.Type == UIEVENT_DBLCLICK )
		{
			DoMouseDown();
		}
		else if(event.Type==UIEVENT_MOUSEMOVE)
		{
			DoMouseMove();
		}
		else if(event.Type==UIEVENT_BUTTONUP)
		{
			DoMouseUp();
		}
		else if(event.Type==UIEVENT_MOUSELEAVE)
		{
			DoMouseLeave();
		}
		else if(event.Type==UIEVENT_TIMER)
		{
			DoTimer();
		}
	}

	void CTabControlUI::DoMouseDown()
	{
		ismousedown=true;
		ClearButtonState(UIEVENT_BUTTONDOWN);
		RECT rect=DisplayRect();
		POINT pt = { 0 };
        ::GetCursorPos(&pt);
        ::ScreenToClient(m_pManager->GetPaintWindow(), &pt);
		lastClickX = pt.x;
		std::vector<CTabControlButton*>::iterator bIter=Buttons.begin();
		for(unsigned int i=0;i<Buttons.size();i++,bIter++)
		{
			CTabControlButton* button=*bIter;
			if(Contains(button->rect,pt))
			{
				button->state=2;
				this->NeedParentUpdate();
				return;
			}
		}
		ClearTabPageState(UIEVENT_BUTTONDOWN);
		std::vector<CTabPage*>::iterator sIter=TabPages.begin();
		for(unsigned int i=0;i<TabPages.size();i++,sIter++)
		{
			CTabPage* tabPage=*sIter;
			if(pt.x>=tabPage->rect.left && pt.x<=tabPage->rect.right)
			{
				tabPage->state=2;
				animation=1;
				lastClickTabX=tabPage->rect.left;
				break;
			}
		}
		this->NeedParentUpdate();
	}

	void CTabControlUI::DoMouseLeave()
	{
		ClearTabPageState(UIEVENT_MOUSEMOVE);
		ClearButtonState(UIEVENT_MOUSEMOVE);
		this->NeedParentUpdate();
	}

	void CTabControlUI::DoMouseMove()
	{
		RECT rect=DisplayRect();
		POINT pt = { 0 };
		::GetCursorPos(&pt);
		::ScreenToClient(m_pManager->GetPaintWindow(), &pt);
		if(animation!=1)
		{
			if(!ismousedown)
			{
				ClearTabPageState(UIEVENT_MOUSEMOVE);
				ClearButtonState(UIEVENT_MOUSEMOVE);
				std::vector<CTabControlButton*>::iterator bIter=Buttons.begin();
				for(unsigned int i=0;i<Buttons.size();i++,bIter++)
				{
					CTabControlButton* button=*bIter;
					if(Contains(button->rect,pt))
					{
						if(button->state!=2)
						{
							button->state=1;
						}
						break;
					}
				}

				std::vector<CTabPage*>::iterator sIter=TabPages.begin();
				for(unsigned int i=0;i<TabPages.size();i++,sIter++)
				{
					CTabPage* tabPage=*sIter;
					if(pt.x>=tabPage->rect.left && pt.x<=tabPage->rect.right)
					{
						if(tabPage->state!=2)
						{
							tabPage->state=1;
						}
						break;
					}
				}
				this->NeedParentUpdate();
			}
		}
	}

	void CTabControlUI::DoMouseUp()
	{
		ismousedown=false;
		POINT pt = { 0 };
        ::GetCursorPos(&pt);
        ::ScreenToClient(m_pManager->GetPaintWindow(), &pt);
		std::vector<CTabControlButton*>::iterator bIter=Buttons.begin();
		for(unsigned int i=0;i<Buttons.size();i++,bIter++)
		{
			CTabControlButton* button=*bIter;
			if(button->state==2)
			{
				if(Contains(button->rect,pt))
				{
					button->state=1;
					if(button->id==ADDTABBTN)
					{
						CTabPage* tabPage=new CTabPage;
						tabPage->caption=m_DefaultTabPageText;
						AddTabPage(tabPage);
					}
					else
					{
						std::vector<CTabPage*>::iterator sIter=TabPages.begin();
						for(unsigned int i=0;i<TabPages.size();i++,sIter++)
						{
							CTabPage* tabPage=*sIter;
							if(tabPage->closebtn==button)
							{
								TabPages.erase(sIter);	
								Buttons.erase(bIter);
								ClearButtonState(UIEVENT_BUTTONDOWN);
								this->NeedParentUpdate();
								return;
							}
						}
					}
				}
				else
				{
					button->state=0;
				}
				break;
			}
		}
		ClearButtonState(UIEVENT_BUTTONDOWN);
		if(animation==1)
		{
			animation=2;
			SetMoving();
		}
		else
		{
			this->NeedParentUpdate();
		}
	}

	void CTabControlUI::DoPaint(HDC hDC, const RECT& rcPaint)
	{
		PaintTabPages(hDC);
	}

	void CTabControlUI::DoTimer()
	{
		SetMoving();
	}

	int CTabControlUI::GetHeaderWidth()
	{
		RECT rc = DisplayRect();
		int width = rc.right- rc.left - 30;
		int headerWidth = 144;
		int tabCount = TabPages.size();
		if(headerWidth * tabCount > width)
		{
			headerWidth = width/tabCount;
		}
		return headerWidth;
	}

	CStdString CTabControlUI::GetBkAddTabPageHotImage()
	{
		return m_sBkAddTabPageHotImage;
	}

	CStdString CTabControlUI::GetBkAddTabPageNormalImage()
	{
		return m_sBkAddTabPageNormalImage;
	}

	CStdString CTabControlUI::GetBkAddTabPagePushedImage()
	{
		return m_sBkAddTabPagePushedImage;
	}

	CStdString CTabControlUI::GetBkCloseTabPageHotImage()
	{
		return m_sBkCloseTabPageHotImage;
	}

	CStdString CTabControlUI::GetBkCloseTabPageNormalImage()
	{
		return m_sBkCloseTagPageNormalImage;
	}

	CStdString CTabControlUI::GetBkCloseTabPagePushedImage()
	{
		return m_sBkCloseTabPagePushedImage;
	}

	CStdString CTabControlUI::GetBkTabPageHotImage()
	{
		return m_sBkTabPageHotImage;
	}
	
	CStdString CTabControlUI::GetBkTabPageNormalImage()
	{
		return m_sBkTabPageNormalImage;
	}
	
	CStdString CTabControlUI::GetBkTabPageSelectedImage()
	{
		return m_sBkTabPageSelectedImage;
	}

	CStdString CTabControlUI::GetDefaultTabPageText()
	{
		return m_DefaultTabPageText;
	}

	CTabPage* CTabControlUI::GetSelectedTabPage()
	{
		std::vector<CTabPage*>::iterator sIter=TabPages.begin();
		for(unsigned int i=0;i<TabPages.size();i++,sIter++)
		{
			CTabPage* tabPage=*sIter;
			if(tabPage->state==2)
			{
				return tabPage;
			}
		}
		return NULL;
	}

	DWORD CTabControlUI::GetTabPageHotFontColor()
	{
		return dw_TabPageHotFontColor;
	}

	DWORD CTabControlUI::GetTabPageNormalFontColor()
	{
		return dw_TabPageNormalFontColor;
	}

	DWORD CTabControlUI::GetTabPageSelectedFontColor()
	{
		return dw_TabPageSelectedFontColor;
	}

	std::vector<CTabPage*> CTabControlUI::GetTabPages()
	{
		return TabPages;
	}

	void CTabControlUI::PaintTabPage(HDC hDC,CTabPage* tabPage)
	{
		if(!tabPage)
		{
			return;
		}
		CStdString tabpage_Image=m_sBkTabPageNormalImage;
		DWORD tabpage_FontColor=dw_TabPageNormalFontColor;
		if(tabPage->state==2)
		{
			tabpage_Image=m_sBkTabPageSelectedImage;
			tabpage_FontColor=dw_TabPageSelectedFontColor;
		}
		else if(tabPage->state==1)
		{
			tabpage_Image=m_sBkTabPageHotImage;
			tabpage_FontColor=dw_TabPageHotFontColor;
		}
		RECT tabRect=CopyRect(tabPage->rect);
		if(animation>0 && tabPage->movingX!=0)
		{
			int width=tabRect.right-tabRect.left;
			tabRect.left=tabPage->movingX;
			tabRect.right=tabRect.left+width;
		}
		CRenderEngine::DrawImageString(hDC, m_pManager, tabRect, tabRect, tabpage_Image, NULL);
		RECT paintRect=tabRect;
		SIZE textSize = CRenderEngine::TextSize(hDC,tabPage->caption);
		RECT textRect;
		textRect.left=paintRect.left+(paintRect.right-paintRect.left)/2 -textSize.cx/2;
		textRect.right=paintRect.left+(paintRect.right-paintRect.left)/2 + textSize.cx/2;
		textRect.top=paintRect.top+(paintRect.bottom-paintRect.top-textSize.cy)/2+2;
		textRect.bottom=textRect.top+textSize.cy;
        CRenderEngine::DrawText(hDC, m_pManager, textRect, tabPage->caption, tabpage_FontColor, \
        13, NULL);

		CTabControlButton* closebtn=tabPage->closebtn;
		CStdString closebtn_Image=m_sBkCloseTagPageNormalImage;
		RECT closeRect=CopyRect(closebtn->rect);
		if(animation>0 && tabPage->movingX!=0)
		{
			closeRect.left=tabPage->movingX+closebtn->rect.left-tabPage->rect.left;
			closeRect.right=closeRect.left+21;
		}
		if(closebtn->state==1)
		{
			closebtn_Image=m_sBkCloseTabPageHotImage;
		}
		else if(closebtn->state==2)
		{
			closebtn_Image=m_sBkCloseTabPagePushedImage;
		}
		CRenderEngine::DrawImageString(hDC,m_pManager,closeRect,closeRect,closebtn_Image,NULL);
	}

	void CTabControlUI::PaintTabPages(HDC hDC)
	{
		ResetLayout();
		CTabPage* selectedTabPage=GetSelectedTabPage();
		if(!selectedTabPage || selectedTabPage->movingX==0)
		{
			CStdString addTabImage=m_sBkAddTabPageNormalImage;
			if(AddTabPageButton->state==1)
			{
				addTabImage=m_sBkAddTabPageHotImage;
			}
			else if(AddTabPageButton->state==2)
			{
				addTabImage=m_sBkAddTabPagePushedImage;
			}
			CRenderEngine::DrawImageString(hDC,m_pManager,AddTabPageButton->rect,AddTabPageButton->rect,addTabImage,NULL);
		}
		std::vector<CTabPage*>::iterator sIter=TabPages.begin();
		for(unsigned int i=0;i<TabPages.size();i++,sIter++)
		{
			CTabPage* tabPage=*sIter;
			if(tabPage->state!=2 && tabPage->movingX==0)
			{
				PaintTabPage(hDC,tabPage);
			}
		}
		sIter=TabPages.begin();
		for(unsigned int i=0;i<TabPages.size();i++,sIter++)
		{
			CTabPage* tabPage=*sIter;
			if(tabPage->state!=2 && tabPage->movingX!=0)
			{
				PaintTabPage(hDC,tabPage);
			}
		}
		PaintTabPage(hDC,selectedTabPage);
	}

	void CTabControlUI::ResetLayout()
	{
		if(timerstart)
		{
			timerstart=!timerstart;
			m_pManager->SetTimer(this,0,1);
		}
		RECT displayRect=DisplayRect();
		int left=displayRect.left;
		int headerWidth = GetHeaderWidth();
		sort(TabPages.begin(),TabPages.end(),Asc);
		std::vector<CTabPage*>::iterator sIter=TabPages.begin();
		for(unsigned int i=0;i<TabPages.size();i++,sIter++)
		{
			CTabPage* tabPage=*sIter;
			RECT rect;
			rect.left=left;
			rect.top=displayRect.top;
			rect.right=left+headerWidth;
			rect.bottom=displayRect.bottom;
			tabPage->rect=rect;
			tabPage->orderNum=i;

			CTabControlButton* closebtn=tabPage->closebtn;
			RECT closeRect;
			closeRect.left=rect.right-24;
			closeRect.top=rect.top+4;
			closeRect.right=rect.right-3;
			closeRect.bottom=rect.top+21;
			closebtn->rect=closeRect;
			left+=headerWidth;
		}

		RECT addRect;
		addRect.left=left;
		addRect.top=displayRect.top;
		addRect.right=left+28;
		addRect.bottom=displayRect.top+26;
		AddTabPageButton->rect=addRect;
	}
	
	void CTabControlUI::SetBkAddTabPageHotImage(CStdString sBkAddTabPageHotImage)
	{
		m_sBkAddTabPageHotImage=sBkAddTabPageHotImage;
	}

	void CTabControlUI::SetBkAddTabPageNormalImage(CStdString sBkAddTabPageNormalImage)
	{
		m_sBkAddTabPageNormalImage=sBkAddTabPageNormalImage;
	}

	void CTabControlUI::SetBkAddTabPagePushedImage(CStdString sBkAddTabPagePushedImage)
	{
		m_sBkAddTabPagePushedImage=sBkAddTabPagePushedImage;
	}

	void CTabControlUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
	{
		if(_tcscmp(pstrName,_T("bkaddtabpagehotimage"))==0)SetBkAddTabPageHotImage(pstrValue);
		else if(_tcscmp(pstrName,_T("bkaddtabpagenormalimage"))==0)SetBkAddTabPageNormalImage(pstrValue);
		else if(_tcscmp(pstrName,_T("bkaddtabpagepushedimage"))==0)SetBkAddTabPagePushedImage(pstrValue);
		else if( _tcscmp(pstrName, _T("bkclosetabpagehotimage")) == 0 ) SetBkCloseTabPageHotImage(pstrValue);
		else if( _tcscmp(pstrName, _T("bkclosetabpagenormalimage")) == 0 ) SetBkCloseTabPageNormalImage(pstrValue);
		else if( _tcscmp(pstrName, _T("bkclosetabpagepushedimage")) == 0 ) SetBkCloseTabPagePushedImage(pstrValue);
		else if( _tcscmp(pstrName, _T("bktabpagenormalimage")) == 0 ) SetBkTabPageNormalImage(pstrValue);
		else if(_tcscmp(pstrName,_T("bktabpagehotimage"))==0) SetBkTabPageHotImage(pstrValue);
		else if(_tcscmp(pstrName,_T("bktabpageselectedimage"))==0) SetBkTabPageSelectedImage(pstrValue);
		else if(_tcscmp(pstrName,_T("defaulttabpagetext"))==0)SetDefaultTabPageText(pstrValue);
		else if(_tcscmp(pstrName,_T("tabpagenormalfontcolor"))==0)
		{
			if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
			LPTSTR pstr = NULL;
			DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
			SetTabPageNormalFontColor(clrColor);
		}
		else if(_tcscmp(pstrName,_T("tabpagehotfontcolor"))==0)
		{
			if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
			LPTSTR pstr = NULL;
			DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
			SetTabPageHotFontColor(clrColor);
		}
		else if(_tcscmp(pstrName,_T("tabpageselectedfontcolor"))==0)
		{
			if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
			LPTSTR pstr = NULL;
			DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
			SetTabPageSelectedFontColor(clrColor);
		}
		else CControlUI::SetAttribute(pstrName, pstrValue);
	}

	void CTabControlUI::SetBkTabPageHotImage(CStdString sBkTabPageHotImage)
	{
		m_sBkTabPageHotImage = sBkTabPageHotImage;
	}

	void CTabControlUI::SetBkTabPageNormalImage(CStdString sBkTabPageNormalImage)
	{
		m_sBkTabPageNormalImage = sBkTabPageNormalImage;
	}

	void CTabControlUI::SetBkTabPageSelectedImage(CStdString sBkTabPageSelectedImage)
	{
		m_sBkTabPageSelectedImage = sBkTabPageSelectedImage;
	}

	void CTabControlUI::SetBkCloseTabPageHotImage(CStdString sBkCloseTabPageHotImage)
	{
		m_sBkCloseTabPageHotImage=sBkCloseTabPageHotImage;
	}

	void CTabControlUI::SetBkCloseTabPageNormalImage(CStdString sBkCloseTagPageNormalImage)
	{
		m_sBkCloseTagPageNormalImage=sBkCloseTagPageNormalImage;
	}

	void CTabControlUI::SetBkCloseTabPagePushedImage(CStdString sBkCloseTabPagePushedImage)
	{
		m_sBkCloseTabPagePushedImage=sBkCloseTabPagePushedImage;
	}

	void CTabControlUI::SetDefaultTabPageText(CStdString defaultTabPageText)
	{
		m_DefaultTabPageText=defaultTabPageText;
		std::vector<CTabPage*>::iterator sIter=TabPages.begin();
		for(unsigned int i=0;i<TabPages.size();i++,sIter++)
		{
			CTabPage* tabPage=*sIter;
			if(tabPage->caption==_T(""))
			{
				tabPage->caption=m_DefaultTabPageText;
			}
		}
	}

	void CTabControlUI::SetMoving()
	{
		if(animation>0)
		{
			if(ismousedown)
			{
				RECT rect=DisplayRect();
				POINT pt = { 0 };
				::GetCursorPos(&pt);
				::ScreenToClient(m_pManager->GetPaintWindow(), &pt);
				CTabPage* selectedTabPage=GetSelectedTabPage();
				int subX=pt.x-lastClickX;
				int newX=lastClickTabX+subX;
				int width=GetHeaderWidth();
				int cwidth=rect.right-rect.left;
				if(newX>0 && newX+width<=cwidth)
				{
					ResetLayout();
					selectedTabPage->movingX=lastClickTabX + subX;
					int movingX=selectedTabPage->movingX;
					int sx=selectedTabPage->rect.left;
					std::vector<CTabPage*>::iterator sIter=TabPages.begin();
					for(unsigned int i=0;i<TabPages.size();i++,sIter++)
					{
						CTabPage* tabPage=*sIter;
						if(tabPage->state!=2)
						{
							bool instead=false;
							int twidth=tabPage->rect.right-tabPage->rect.left;
							int tleft=tabPage->rect.left;
							if((movingX>tleft-twidth/2+20 && movingX<tleft-twidth/2+60)
								|| (i==TabPages.size()-1 && movingX>tleft+twidth))
							{
								instead=true;
							}
							else if(movingX>tleft+twidth/2-60 && movingX<tleft+twidth/2-20)
							{
								instead=true;
							}
							if(instead)
							{
								tabPage->movingX=tleft;
								int oderNum=selectedTabPage->orderNum;
								selectedTabPage->orderNum=tabPage->orderNum;
								tabPage->orderNum=oderNum;
							}
						}
					}
					ResetLayout();
				}
			}
			bool drawing=false;
			std::vector<CTabPage*>::iterator sIter=TabPages.begin();
			for(unsigned int i=0;i<TabPages.size();i++,sIter++)
			{
				CTabPage* tabPage=*sIter;
				if(tabPage->state ==2 && animation ==1)
				{
					continue;
				}
				if(tabPage->movingX!=0)
				{
					int x = tabPage->rect.left;
					int relativeX=tabPage->movingX;
					int sub=abs(x-relativeX);
					int step=20;
					if(tabPage->state==2)
					{
						if(sub>200)
						{
							step=sub/200*100;
						}
					}
					else
					{
						step=10;
					}
					if(relativeX!=x)
					{
						if(x>relativeX+step)relativeX+=step;
						else if(x<relativeX-step)relativeX-=step;
						else relativeX=x;
						tabPage->movingX=relativeX;
						drawing=true;
					}
					else
					{
						tabPage->movingX=0;
					}
				}
			}
			if(!drawing)
			{
				if(animation==2)
				{
					animation=0;
				}
			}
			this->NeedParentUpdate();
		}
	}

	void CTabControlUI::SetSelectedTabPage(CTabPage* tabPage)
	{
		ClearTabPageState(UIEVENT_BUTTONDOWN);
		tabPage->state=2;
	}

	void CTabControlUI::SetTabPageHotFontColor(DWORD TabPageHotFontColor)
	{
		dw_TabPageHotFontColor=TabPageHotFontColor;
	}

	void CTabControlUI::SetTabPageNormalFontColor(DWORD TabPageNormalFontColor)
	{
		dw_TabPageNormalFontColor=TabPageNormalFontColor;
	}

	void CTabControlUI::SetTabPageSelectedFontColor(DWORD TabPageSelectedFontColor)
	{
		dw_TabPageSelectedFontColor=TabPageSelectedFontColor;
	}

	void CTabControlUI::SetPos(RECT rc)
	{
		CControlUI::SetPos(rc);
	}
}